home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 8: LINUX Games
/
Linux Cubed Series 8 - LINUX Games.iso
/
games
/
video
/
thrust-s.53
/
thrust-s
/
thrust
/
src
/
thrust.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-11-06
|
18KB
|
928 lines
/* Written by Peter Ekberg, peda@lysator.liu.se */
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#include <vgagl.h>
#include <vga.h>
#include <vgakeyboard.h>
#include "thrust.h"
void *keyintadr;
byte *bulletmap;
Palette *palette;
byte *blocks;
byte *ship;
byte *shieldship;
byte *bana;
byte *fuelmap;
byte *loadmap;
byte *shipstorage;
byte *bulletstorage;
byte *fragmentstorage;
byte *fuelstorage;
byte *loadstorage;
byte *wirestorage;
word lenx; /* Banans max i x-len, anvΣnds senare till den aktuella */
word leny; /* Banans max i y-len, storleken pσ banan. SΣtts i readbana() */
word lenx3,leny3;
/* Status of game. */
int alpha,deltaalpha;
word loaded,loadcontact,loadpointshift;
int loadpoint;
int countdown;
word crash,shoot,repetetive;
word refueling;
int speedx,speedy;
long absspeed,oldabs;
int kdir,dir;
int shipdx,shipdy;
int x,y; /* ╓vre vΣnstra h÷rnet 8 enh. per pixel. */
int pixx,pixy; /* ╓vre vΣnstra h÷rnet i pixels. */
int pblockx,pblocky; /* ╓vre vΣnstra h÷rnet i block. */
int vx,vy; /* Skeppets hastighet. */
int bildx,bildy; /* ╓vre vΣnstra h÷rnet av fuskbilden i pixels. */
int bblockx,bblocky; /* ╓vre vΣnstra h÷rnet av fuskbilden i block. */
int loadbx,loadby; /* Lastens placering pσ banan i blocks. */
int gravity;
int score;
byte shield;
byte colorr, colorg, colorb;
#define checkfork(b,a) \
case b-1: \
if(easyrider==a || easyrider==a+1) \
easyrider=a+1; \
else \
easyrider=-1; \
break
int
insideblock(blockx, blocky, pblockx, pblocky, sx, sy)
int blockx, blocky, pblockx, pblocky, sx, sy;
{
return((blockx>=pblockx-sx) && (blockx<pblockx+BBILDX) &&
(blocky>=pblocky-sy) && (blocky<pblocky+BBILDY));
}
int
insidepixel(x, y, pixx, pixy, sx, sy)
int x, y, pixx, pixy, sx, sy;
{
return((x>pixx-sx) && (x<pixx+PSCRX) &&
(y>pixy-sy) && (y<pixy+PSCRY));
}
void
updateborder(pblockx, pblocky, bblockx, bblocky, vx, vy)
int pblockx, pblocky, bblockx, bblocky;
int vx, vy;
{
word k;
if(vy>0)
for(k=0; k<BBILDX; k++)
putblock(bblockx+k, (bblocky+BBILDY-1)%BBILDY, blocks+
(*(bana+(pblockx+k)%lenx+((pblocky+BBILDY-1)%leny)*lenx)<<6));
else
for(k=0; k<BBILDX; k++)
putblock(bblockx+k, bblocky, blocks+
(*(bana+(pblockx+k)%lenx+(pblocky%leny)*lenx)<<6));
if(vx>0)
for(k=0; k<BBILDY; k++)
putblock(bblockx+BBILDX-1, (bblocky+k)%BBILDY, blocks+
(*(bana+(pblockx+BBILDX-1)%lenx+((pblocky+k)%leny)*lenx)<<6));
else
for(k=0; k<BBILDY; k++)
putblock(bblockx, (bblocky+k)%BBILDY, blocks+
(*(bana+pblockx%lenx+((pblocky+k)%leny)*lenx)<<6));
}
void
fade_in()
{
int i;
for(i=1; i<=64; i++)
fadepalette(0,255,palette,i,1);
}
void
fade_out()
{
int i;
for(i=64; i; i--)
fadepalette(0,255,palette,i,1);
gl_clearscreen(0);
vga_setpage(0);
usleep(500000L);
}
void
pause_message()
{
char *str[] = {
"GAME PAUSED.",
"PRESS 'C' TO CONTINUE..." };
chflag=1;
gcenter(80,str[0]);
gcenter(91,str[1]);
chflag=0;
}
void
escape_message()
{
char *str[] = {
"ARE YOU SURE YOU WANT TO QUIT (Y/N)?" };
chflag=1;
gcenter(85,str[0]);
chflag=0;
}
enum {
pause_bit =1<<0,
escape_bit=1<<1,
right_bit =1<<2,
left_bit =1<<3,
fire_bit =1<<4,
pickup_bit=1<<5,
thrust_bit=1<<6,
quit_bit =1<<7
};
byte
whatkeys()
{
byte keybits=0;
/* Use this to create a demo. */
/*
static FILE *f=NULL;
if(f == NULL)
f=fopen("foobarfoo", "w");
*/
keyboard_update();
if(keyboard_keypressed(SCANCODE_P))
keybits|=pause_bit;
else if(keyboard_keypressed(SCANCODE_ESCAPE) ||
keyboard_keypressed(SCANCODE_Q))
keybits|=escape_bit;
if(keyboard_keypressed(SCANCODE_S))
keybits|=right_bit;
if(keyboard_keypressed(SCANCODE_A))
keybits|=left_bit;
if(keyboard_keypressed(SCANCODE_ENTER))
keybits|=fire_bit;
if(keyboard_keypressed(SCANCODE_SPACE))
keybits|=pickup_bit;
if(keyboard_keypressed(SCANCODE_RIGHTCONTROL))
keybits|=thrust_bit;
/*
fputc((keybits&escape_bit)?quit_bit:escape_bit, f);
*/
return(keybits);
}
byte
nextmove(int reset)
{
static byte *p;
byte retbits=0;
if(reset) {
keyboard_update();
p=&bin_demomoves[0];
}
else if(keyboard_update())
retbits=quit_bit;
else {
retbits=*(p++);
retbits&=~thrust_bit;
retbits|=*(p-!!(random()%30)) & thrust_bit;
}
return(retbits);
}
int
game(int demo)
{
byte actionbits=0;
int ax,ay,aradial,acircum;
word lives,endlevel;
word dying;
word alive;
word fuel;
int l;
word wrapers;
int level;
int round;
static char **levels[LEVELS] = { level1, level2, level3, level4 };
static char textstr[40];
int localscore;
options end;
int ch;
int lastlevel;
int easyrider=0;
int restartx=0, restarty=0;
restartpoint *restartxy;
int gravitymsg;
int teleport;
if(demo)
nextmove(1);
lives=3; /* 3 */
localscore=0;
score=0;
round=0; /* 0 */
level=0; /* 0 */
lastlevel=-1;
shield=0;
fuel=1000; /* 1000 */
gravitymsg=0;
teleport=0;
while(level<LEVELS && lives>0 && fuel) {
endlevel=0;
wrapers=0;
dying=0;
alive=1;
srandom(time(NULL));
if(level!=lastlevel || !spacestation) {
if(level==0 && lastlevel!=-1)
gravitymsg=1;
if(!readbana(levels[level])) {
printf("Illegal definition of level %d.\n", level+1);
return(1);
}
restartx=0;
restarty=0;
initgame(round, 1, 0, 0);
}
else
initgame(round, 0, restartx, restarty);
initscreen();
putscr(pixx%PBILDX,pixy%PBILDY);
lastlevel=level;
printgs(250,188,"FUEL");
sprintf(textstr,"LIVES: %d",lives);
printgs(20,192,textstr);
sprintf(textstr,"SCORE: %d",score);
printgs(20,184,textstr);
sprintf(textstr,"LEVEL %d", level+1);
gcenter(70, textstr);
if(gravitymsg)
gcenter(60, (round&1) ? "REVERSED GRAVITY": "NORMAL GRAVITY");
gravitymsg=0;
fade_in();
usleep(750000UL);
vga_waitretrace();
putscr(pixx%PBILDX,pixy%PBILDY);
while(!endlevel) {
actionbits=demo ? nextmove(0) : whatkeys();
if(actionbits&quit_bit)
endlevel=1;
if(actionbits&pause_bit) {
pause_message();
keyboard_close();
vga_unlockvc();
end=NOTHING;
while(vga_getkey());
while(end==NOTHING) {
ch=vga_getkey();
switch(tolower(ch)) {
case 'p':
easyrider=0;
break;
case 'M':
checkfork('m', 0);
checkfork('b', 1);
checkfork('z', 2);
checkfork('h', 3);
checkfork('s', 4);
checkfork('p', 5);
checkfork('v', 6);
checkfork('o', 7);
checkfork('e', 8);
break;
case 'c':
case 'q':
case 27:
end=PLAY;
break;
}
usleep(10000UL);
}
if(easyrider!=9)
easyrider=0;
vga_lockvc();
keyboard_init();
}
if(actionbits&escape_bit) {
escape_message();
keyboard_close();
vga_unlockvc();
end=NOTHING;
while(end==NOTHING) {
ch=vga_getkey();
switch(tolower(ch)) {
case 'y':
end=END;
endlevel=1;
level=LEVELS;
break;
case 'n':
end=PLAY;
break;
}
usleep(10000UL);
}
vga_lockvc();
keyboard_init();
}
if(alive && (actionbits&right_bit)) {
decr(kdir,0,96);
dir=kdir/3;
}
if(alive && (actionbits&left_bit)) {
incr(kdir,96,0);
dir=kdir/3;
}
if(alive && (actionbits&fire_bit)) {
if(!shoot) {
shoot=1;
newbullet(x+((160+shipdx)<<3)+(sinus[(dir+8)&31]>>2),
y+((88+shipdy)<<3)-(sinus[dir]>>2),
(speedx+(sinus[(dir+8)&31]<<5))>>8,
(speedy-(sinus[dir]<<5))>>8,
kdir/6,1);
}
else if(repetetive || easyrider)
shoot=0;
}
else
shoot=0;
refueling=0;
if(alive && (actionbits&pickup_bit)) {
if(fuel>0) {
if(shield++==3) {
#ifndef DEBUG
if(!easyrider)
fuel--;
#endif
shield=1;
}
}
else
shield=0;
l=closestfuel((pixx+shipdx+160)%lenx3,
(pixy+shipdy+88)%leny3);
if(l>=0)
if(resonablefuel((pixx+shipdx+160)%lenx3,
(pixy+shipdy+88)%leny3,l)) {
#ifndef DEBUG
if(!easyrider)
fuel+=6;
#endif
refueling=1;
things[l].alive--;
if(things[l].alive==1)
things[l].score=300;
}
if(!loaded)
if(inloadcontact((pixx+shipdx+160)%lenx3,
(pixy+shipdy+88)%leny3)) {
loadcontact=1;
*(bana+lenx*loadby+loadbx)=32;
drawload(0);
}
}
else {
shield=0;
if(alive && loadcontact) {
*(bana+lenx*loadby+loadbx)=253;
drawload(1);
loadcontact=0;
}
}
if(alive && (actionbits&thrust_bit)) {
if(fuel>0) {
#ifndef DEBUG
if(!easyrider)
fuel--;
#endif
oldabs=speedx*(long)speedx+speedy*(long)speedy;
if(loaded) {
aradial=(SPEED*sinus2[((dir<<5)-alpha+256)&1023]) >> 8;
acircum=(SPEED*sinus2[((dir<<5)-alpha)&1023]) >> 9;
ax=(aradial*(SPEED*sinus2[(alpha+256)&1023] >> 8)) >> 10;
ay=(-aradial*(SPEED*sinus2[alpha] >> 8)) >> 10;
deltaalpha=deltaalpha+acircum;
deltaalpha=min(deltaalpha, 16384);
deltaalpha=max(deltaalpha, -16384);
}
else {
ax=SPEED*sinus[(dir+8)&31]>>9;
ay=-SPEED*sinus[dir]>>9;
}
speedx+=ax;
speedy+=ay;
absspeed=speedx*(long)speedx+speedy*(long)speedy;
if(absspeed>1000000000L && absspeed>oldabs) {
speedx-=ax;
speedy-=ay;
}
}
}
if(loaded) {
if(loadpointshift) {
speedx+=shipdx*12;
speedy+=shipdy*12;
}
alpha=(alpha+(deltaalpha>>9))&1023;
loadpointshift=0;
if(++loadpoint>126)
loadpoint=126;
else
loadpointshift=1;
shipdx=(sinus2[(alpha+256)&1023]*loadpoint)/1512;
shipdy=(-sinus2[alpha]*loadpoint)/1512;
if(loadpointshift) {
speedx-=shipdx*12;
speedy-=shipdy*12;
}
if(deltaalpha>0)
deltaalpha=deltaalpha-(deltaalpha>>10)-1;
else if(deltaalpha<0)
deltaalpha=deltaalpha-(deltaalpha>>10)+1;
if(abs(deltaalpha)<2)
deltaalpha=0;
}
else
shipdx=shipdy=0;
/* Gravity and Aerodynamics */
if(speedx>0)
speedx=speedx-(speedx>>9)-1;
else if(speedx<0)
speedx=speedx-(speedx>>9)+1;
if(alive) {
speedy+=SPEED*gravity>>8;
if(speedy>0)
speedy--;
else if(speedy<0)
speedy++;
/* Move the Ship */
speedx=min(speedx,16384);
speedx=max(speedx,-16384);
speedy=min(speedy,16384);
speedy=max(speedy,-16384);
vx=speedx>>8;
vy=speedy>>8;
x=(x+vx+(lenx<<6))%(lenx<<6);
y=(y+vy+(leny<<6))%(leny<<6);
}
/* Bunkerfire */
bunkerfirebullets();
movebullets();
movefragments();
drawfuel(fuel);
/* Move the Spacestationblip */
scount=(scount+1)&15;
if(!scount && spacestation && ssblip)
ssblip--;
if(!spacestation) {
countdown--;
if(countdown<0) {
#ifndef DEBUG
if(alive && !easyrider) {
dying=1;
}
#endif
}
else {
chflag=1;
if(countdown&16)
chcolor=0;
else
chcolor=20;
sprintf(textstr,"%d ",(countdown+99)/100);
printgs(155,180,textstr);
chcolor=20;
chflag=0;
}
}
/* Precalculate some values */
pixx=x>>3;
pixy=y>>3;
bildx=(pixx+PBILDX-4)%PBILDX+4;
bildy=pixy%PBILDY;
pblockx=pixx>>3;
pblocky=pixy>>3;
bblockx=bildx>>3;
bblocky=bildy>>3;
if(wrapers)
if(pblocky>BBILDY && pblocky<2*BBILDY) {
y-=PBILDY<<3;
pixy-=PBILDY;
pblocky-=BBILDY;
unwrapbullets();
unwrapfragments();
wrapers--;
}
if(pblocky>leny-3) {
if(loaded) {
endlevel=1;
teleport=1;
if(!easyrider)
localscore+=4000+400*level-2000*spacestation;
if(++level==LEVELS) {
level=0;
round=(round+1)%4;
}
}
y+=(PBILDY-leny3)<<3;
pixy+=PBILDY-leny3;
pblocky+=BBILDY-leny;
wrapbullets();
wrapfragments();
if(!++wrapers)
wrapers--;
}
/* Check if at a restart barrier. If so, update the restart point. */
restartxy=atbarrier((pblockx+((154+shipdx)>>3))%lenx,
pblocky+((82+shipdy)>>3));
if(restartxy) {
restartx=(restartxy->x-(154>>3))%lenx;
restarty=restartxy->y-(82>>3);
}
/* Scroll the screen */
setmargin(253,1);
updateborder(pblockx,pblocky,bblockx,bblocky,vx,vy);
drawspacestationblip();
setmargin(255,1);
drawbullets();
if(alive)
crash=drawshuttle();
drawfragments();
if(alive && refueling)
drawfuellines();
/* Check if end of life. */
#ifndef DEBUG
if(!easyrider)
if(alive && crash) {
lives--;
dying=1;
}
#endif
/* Wait for the screen retrace and then dump the graphics to it. */
setmargin(crash,1);
vga_waitretrace();
setmargin(crash,1);
/* Screendump */
/* if(keyboard_keypressed(63)) *//* F5 */
/* savegraphics(bildx,bildy);*/
putscr(bildx,bildy);
/* Remove moveable objects from screen in reverse order. */
if(alive && refueling)
undrawfuellines();
setmargin(120,1);
undrawfragments();
if(alive)
undrawshuttle();
undrawbullets();
/* Remove objects */
if(!easyrider)
localscore+=killdyingthings();
else
killdyingthings();
if(dying) {
alive=0;
dying=0;
explodeship();
}
if(!alive && !livefragments())
endlevel=1;
animatesliders();
if(localscore>score) {
chflag=1;
if(localscore/10000 > score/10000) {
lives++;
sprintf(textstr,"LIVES: %d",lives);
printgs(20,192,textstr);
}
score=localscore;
sprintf(textstr,"SCORE: %d ",score);
printgs(20,184,textstr);
chflag=0;
}
}
if(teleport)
drawteleport();
teleport=0;
if(!(actionbits&(quit_bit|escape_bit)))
usleep(1000000UL);
fade_out();
if(demo)
level=LEVELS;
}
return(0);
}
void
pressanykey()
{
keyboard_close();
vga_unlockvc();
do
usleep(10000UL);
while(!vga_getkey());
vga_lockvc();
keyboard_init();
}
int
instructions()
{
int i;
static char *keys[] = {
"'A'", "'S'", "'ENTER'", "'R-CTRL'", "'SPACE'", "'ESC'", "'P'", "'C'" };
static char *func[] = {
"TURN LEFT", "TURN RIGHT", "FIRE", "THRUST",
"PICK UP AND SHIELD", "QUIT GAME (Q=ESC)", "PAUSE", "CONTINUE" };
gcenter(50, "THE FOLLOWING KEYS ARE USED:");
for(i=0; i<8; i++) {
chcolor++;
printgs(140-gstrlen(keys[i]), 63+i*8+2*(i>4), keys[i]);
chcolor--;
printgs(145, 63+i*8+2*(i>4), func[i]);
}
gcenter(150, "PRESS ANY KEY FOR MAIN MENU.");
fade_in();
pressanykey();
fade_out();
return(0);
}
int
about()
{
int i;
char *str[] = {
"THRUST VERSION " VERSION,
"",
"WRITTEN BY",
"",
"PETER EKBERG",
"PEDA@LYSATOR.LIU.SE",
"",
"THANKS TO THE AUTHORS",
"OF THE ORIGINAL",
"FOR THE C64.",
NULL
};
for(i=0; str[i]; i++)
gcenter(40+9*i, str[i]);
gcenter(145, "PRESS ANY KEY FOR MAIN MENU.");
fade_in();
pressanykey();
fade_out();
return(0);
}
char *
enterhighscorename()
{
static char name[40];
char str[40];
strcpy(name, standardname());
sprintf(str, "YOU MANAGED %d POINTS!", score);
gcenter(64, str);
gcenter(75, "YOU MADE IT INTO THE HIGHSCORE LIST!");
gcenter(86, "ENTER YOUR NAME:");
printgs(130,97,name);
fade_in();
keyboard_close();
vga_unlockvc();
if(readgs(130, 97, name, 39, 80, 0)==-1)
strcpy(name, standardname());
vga_lockvc();
keyboard_init();
fade_out();
return(name);
}
int
showhighscores()
{
char str[100];
byte tmp=chcolor;
int i;
int scorew, namew;
int len;
gcenter(50, "THE CURRENT HIGHSCORES ARE");
scorew=namew=0;
for(i=0; i<HIGHSCORES; i++) {
sprintf(str, "%d", highscorelist[i].score);
len=gstrlen(str);
if(len>scorew)
scorew=len;
len=gstrlen(highscorelist[i].name);
if(len>namew)
namew=len;
}
for(i=0; i<HIGHSCORES; i++) {
sprintf(str, "%d", highscorelist[i].score);
chcolor=12;
printgs(155+(scorew-namew)/2-gstrlen(str), 70+11*i, str);
chcolor=13;
printgs(165+(scorew-namew)/2, 70+11*i, highscorelist[i].name);
}
chcolor=tmp;
gcenter(145, "PRESS ANY KEY FOR MAIN MENU.");
fade_in();
pressanykey();
fade_out();
return(0);
}
void
newhighscore()
{
char *name;
name = enterhighscorename();
inserthighscore(name, score);
writehighscores();
showhighscores();
}
options
menu()
{
int i,j;
options end=NOTHING;
int ch;
static char *menuchoises[NOTHING]= { "I", "H", "P", "A", "Q" };
static char *menuoptions[NOTHING]= {
"INSTRUCTIONS", "HIGHSCORES", "PLAY GAME", "ABOUT", "QUIT" };
int count=0;
for(i=0; i<150; i++)
for(j=0; j<300; j++)
*(graph_mem+(i+15)*320+j+10)=intro[i*300+j]+192;
for(i=0; i<NOTHING; i++) {
chcolor--;
gcenter(130+i*11,menuoptions[i]);
chcolor++;
printgs(160-(gstrlen(menuoptions[i])>>1), 130+i*11, menuchoises[i]);
}
fade_in();
keyboard_close();
vga_unlockvc();
while(end==NOTHING) {
ch=vga_getkey();
switch(tolower(ch)) {
case 'i':
end=INST;
break;
case 'p':
end=PLAY;
break;
case 'h':
end=HI;
break;
case 'a':
end=ABOUT;
break;
case 'd':
end=DEMO;
break;
case 'q':
case 27:
end=END;
break;
default:
break;
}
usleep(10000UL);
/* You may want to comment the following statement out if you don't
want your box to keep running the demo every once in a while. */
if(++count==800)
end=DEMO;
}
vga_lockvc();
keyboard_init();
fade_out();
return(end);
}
int
main(int argc, char *argv[])
{
int end=0;
uid_t uid;
/* Keep root priviliges for highscore file.
If you have security concerns and do not
care about the highscore file, remove the
setreuid() and getuid() calls surrounding
the call to inithardware() */
uid=getuid();
setreuid(0,-1);
inithardware();
setreuid(uid, -1);
if(!initmem()) {
restorehardware();
return(1);
}
inithighscorelist();
sleep(1);
while(!end) {
switch(menu()) {
case INST:
instructions();
break;
case PLAY:
if(!(end=game(0)))
if(ahighscore(score))
newhighscore();
break;
case HI:
showhighscores();
break;
case ABOUT:
about();
break;
case DEMO:
game(1);
break;
case END:
end=1;
break;
default:
break;
}
}
restoremem();
restorehardware();
return(0);
}